package com.hemerasolutions.v2trainer.controller;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.el.ELContext;
import javax.el.ValueExpression;
import javax.faces.application.FacesMessage;
import javax.faces.application.FacesMessage.Severity;
import javax.faces.context.FacesContext;
import javax.imageio.ImageIO;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;

import org.primefaces.context.RequestContext;
import org.primefaces.event.FileUploadEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
//import org.springframework.security.core.Authentication;
//import org.springframework.security.core.context.SecurityContextHolder;



import org.springframework.context.NoSuchMessageException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;

import com.hemerasolutions.v2trainer.controller.interfaces.BaseBeanInterface;
import com.hemerasolutions.v2trainer.model.interfaces.AgreementHolderInterface;
import com.hemerasolutions.v2trainer.model.library.Library;
import com.hemerasolutions.v2trainer.model.multimedia.Photo;
import com.hemerasolutions.v2trainer.model.others.Theme;
import com.hemerasolutions.v2trainer.model.users.Academy;
import com.hemerasolutions.v2trainer.model.users.Admin;
import com.hemerasolutions.v2trainer.model.users.Athlete;
import com.hemerasolutions.v2trainer.model.users.PersonalTrainer;
import com.hemerasolutions.v2trainer.model.users.Teacher;
import com.hemerasolutions.v2trainer.model.users.User;
import com.hemerasolutions.v2trainer.service.interfaces.LibraryServiceInterface;
import com.hemerasolutions.v2trainer.service.interfaces.UserServiceInterface;



public class BaseBean implements BaseBeanInterface{

	private static final long serialVersionUID = 1L;

    @Autowired
	private MessageSource messageSource;

    @Autowired
    private UserServiceInterface userService;

    @Autowired
    private LibraryServiceInterface libraryService; 

    private User activeUser;
    
	private List<Theme> advancedThemes;
	
	private List<Library> librarys;

	private String greetings;

       
	public void init(){
		this.setAdvancedThemes(userService.listThemes());		
	}
	
	@Override
	public ServletContext getServletContext() {
		return (ServletContext) FacesContext.getCurrentInstance().getExternalContext().getContext();
	}


	@Override
	public void addMessage(String titulo, String message, Severity severity){
		FacesMessage facesMessage =  new FacesMessage(severity,titulo,message);
		FacesContext.getCurrentInstance().addMessage(null, facesMessage);
	}
	
	@Override
	public void showInfoMessage(String title, String message){
		this.addMessage(title , message, FacesMessage.SEVERITY_INFO);
	}
	
	@Override
	public void showErrorMessage(String title, String message){
		this.addMessage(title , message, FacesMessage.SEVERITY_ERROR);
	}
	
	@Override
	public void showWarnMessage(String title, String message){
		this.addMessage(title , message, FacesMessage.SEVERITY_WARN);
	}
	
	@Override
	public String localizedText(String id){
		
        ServletRequest request = (ServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
        String message;
        try {
            message = messageSource.getMessage((String) id, null, request.getLocale());
        }
        catch (NoSuchMessageException e) {
            message = "???" + id + "???";
        }
        return message;
		
	}

	@Override
	public long getSerialversionuid() {
		return serialVersionUID;
	}

	@Override
	public MessageSource getMessageSource() {
		return messageSource;
	}

	@Override
	public UserServiceInterface getUserService() {
		return userService;
	}

	@Override
	public void setMessageSource(MessageSource messageSource) {
		this.messageSource = messageSource;
	}

	@Override
	public void setUserService(UserServiceInterface userService) {
		this.userService = userService;
	}

	@Override
	public Photo uploadPhoto(FileUploadEvent ev, Photo photo) {

		photo.setContent(this.resizeImage(ev.getFile().getContents(),photo.getHeight(),photo.getWidth()));

		return photo;
		
	}

	
	@Override
	public byte[] resizeImage(byte[] imagem, int height, int width){

	ByteArrayOutputStream buffer = new ByteArrayOutputStream();         
		
    try {    
		BufferedImage newImage    = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
		BufferedImage oldImage 	 = ImageIO.read(new ByteArrayInputStream(imagem));
		Graphics2D 	  graphic  	 = newImage.createGraphics();
		graphic.drawImage(oldImage, 0, 0, width, height, null);
		graphic.dispose();
        ImageIO.write(newImage, "JPG", buffer);    

    	} catch (Exception e) {    
	        e.printStackTrace();    
	    }    

	    return buffer.toByteArray(); 
	}
	
	@Override
	public void updatePFComponnent(String pfComponent){
		RequestContext context = RequestContext.getCurrentInstance(); 
		context.update(pfComponent);
		System.out.println("Update of:" + pfComponent );
	}
		
	@Override
	public void executeJavascript(String script){
		RequestContext context = RequestContext.getCurrentInstance();
		context.execute(script);	
		
	}
		

	public int getActiveUserType(){

		Authentication auth = SecurityContextHolder.getContext().getAuthentication();
		if(auth == null){
			return 0;
		}else{
			if(this.activeUser == null){
				this.activeUser = userService.getUserByUserEmail(auth.getName());
			}

			return this.activeUser.getUserType();
		}
	}


	public User getActiveUser(){
		Authentication auth = SecurityContextHolder.getContext().getAuthentication();

		if(auth == null){
			return null;
		}else{
			if(this.activeUser == null){
				this.activeUser = userService.getUserByUserEmail(auth.getName());
			}
			return this.activeUser;
		}
	}

	public List<AgreementHolderInterface> getAgreementHolders(){
		List<AgreementHolderInterface> agreements = new ArrayList<AgreementHolderInterface>();
		
		if(this.getActiveUserType() == User.USERTYPE_ATHLETE){
			agreements.addAll(this.getActiveActor(Athlete.class).getAcademys());
			agreements.addAll(this.getActiveActor(Athlete.class).getPersonalTrainers());
			
		}

		return agreements;
	}
	
	public <T> T getActiveActor( Class<T> type){

		Authentication auth = SecurityContextHolder.getContext().getAuthentication();
		User user = userService.getUserByUserEmail(auth.getName());
		return userService.getActiveUser(user,type);
		

	}
	
	@Override
	public <T> T getCCValue(String name,  Class<T> type){
		FacesContext facesContext = FacesContext.getCurrentInstance();
		ELContext elContext = facesContext.getELContext();
		ValueExpression valueExpression = facesContext.getApplication().getExpressionFactory().createValueExpression(elContext, "#{cc.attrs."+name+"}", type);

		return type.cast(valueExpression.getValue(elContext));				
	}

	@Override
	public <T> void setCCValue(String name, Object value , Class<T> type ){

		FacesContext facesContext = FacesContext.getCurrentInstance();
		ELContext elContext = facesContext.getELContext();
		ValueExpression valueExpression = facesContext.getApplication().getExpressionFactory().createValueExpression(elContext, "#{cc.attrs."+name+"}", type);

		valueExpression.setValue(elContext, type.cast(value));				
	}	
	
	@Override
	public <T> T getContextValue(String name,  Class<T> type){
		FacesContext facesContext = FacesContext.getCurrentInstance();
		ELContext elContext = facesContext.getELContext();
		ValueExpression valueExpression = facesContext.getApplication().getExpressionFactory().createValueExpression(elContext, name, type);

		return type.cast(valueExpression.getValue(elContext));				
	}

	@Override
	public <T> void setContextValue(String name, Object value , Class<T> type ){

		FacesContext facesContext = FacesContext.getCurrentInstance();
		ELContext elContext = facesContext.getELContext();
		ValueExpression valueExpression = facesContext.getApplication().getExpressionFactory().createValueExpression(elContext, name, type);

		valueExpression.setValue(elContext, type.cast(value));				
	}	

	
	
	public List<Theme> getAdvancedThemes() {
		return advancedThemes;
	}

	public void setAdvancedThemes(List<Theme> advancedThemes) {
		this.advancedThemes = advancedThemes;
	}
	
	@Override
	public Date endDayDateHour(Date dt) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(dt);
		cal.set(Calendar.HOUR_OF_DAY, 23);
		cal.set(Calendar.MINUTE, 59);
		cal.set(Calendar.SECOND, 59);
		
		return cal.getTime();
	}

	@Override
	public Date begDayDateHour(Date dt) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(dt);
		cal.set(Calendar.HOUR_OF_DAY, 00);
		cal.set(Calendar.MINUTE, 00);
		cal.set(Calendar.SECOND, 00);
		
		return cal.getTime();
	}
	
	
	public List<Library> getActiveUserAllowedLibrarys(){

		if(librarys == null){
			this.librarys = new ArrayList<Library>();
			switch (this.getActiveUserType()) {
				case User.USERTYPE_ACADEMY:
					librarys.addAll(libraryService.readLibrarys(this.getActiveActor(Academy.class)));
					break;
				case User.USERTYPE_ADMIN:
					librarys.addAll(libraryService.readLibrarys(this.getActiveActor(Admin.class)));
					break;
				case User.USERTYPE_ATHLETE:
					librarys.addAll(libraryService.readLibrarys(this.getActiveActor(Athlete.class)));
					break;
				case User.USERTYPE_PT:
					librarys.addAll(libraryService.readLibrarys(this.getActiveActor(PersonalTrainer.class)));
					break;
				case User.USERTYPE_TEACHER:
					librarys.addAll(libraryService.readLibrarys(this.getActiveActor(Teacher.class)));
					break;
				default:
					break;
			}
			
			for(Library lib:this.readPublicLibrarys()){
				if(!librarys.contains(lib)){
					librarys.add(lib);
				}
			}			
		}

		return librarys;
	}


	public String getGreetings(){

		if(greetings == null){
			switch (this.getActiveUserType()) {
				case User.USERTYPE_ACADEMY:
					Academy academy = this.getActiveActor(Academy.class);
					greetings =	academy.getOwner();
					break;
				case User.USERTYPE_ADMIN:
					Admin admin = this.getActiveActor(Admin.class);
					greetings =  admin.getFirstName() + " " + admin.getLastName();
					break;
				case User.USERTYPE_ATHLETE:
					Athlete athlete = this.getActiveActor(Athlete.class);
					greetings = athlete.getFirstName() + " " + athlete.getLastName();
					break;
				case User.USERTYPE_PT:
					PersonalTrainer pt = this.getActiveActor(PersonalTrainer.class);
					greetings = pt.getFirstName() + " " + pt.getLastName();
					break;
				case User.USERTYPE_TEACHER:
					Teacher teacher = this.getActiveActor(Teacher.class);
					greetings = teacher.getFirstName() + " " + teacher.getLastName();
					break;
				default:
					greetings = this.localizedText("User");
			}
				
		}
		
		return greetings;
	}
	private List<Library> readPublicLibrarys() {
	
		return this.libraryService.readPublicLibrarys();

	}
	
	
}
